"""asyncserver.IOAsyncServer"""


import asyncore
import socket
import sys


from coffeetalk.protocol import iotypes
from coffeetalk.utilities import iologger
from coffeetalk.server import asyncconnection

class IOAsyncServer(asyncore.dispatcher):
    """ip,port,userclass,log"""

    def __init__(self,ip,port,userclass,iotrees,log):
        
        self.map = {}
        asyncore.dispatcher.__init__(self,map=self.map)
        
        self.userclass = userclass
        self.iotrees = iotrees
        self.env = iotypes.Environment('0.0.0.0','asyncserver.py','Internal',str(id(self)),'0')
        self.log = log
        
        self.ip = ip
        self.port = port
            
    def make_socket(self):
        
        try:
            self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
            self.set_reuse_addr()
            self.bind((self.ip,int(self.port)))
            self.listen(socket.SOMAXCONN)
            self.log.log_error(iologger.DEBUG,'0.0.0.0',self.env.username,self.env.group,iologger.current_function(),'OK','')
        except:
            type,value = sys.exc_info()[:2]
            self.log.log_error(iologger.CRITICAL,'0.0.0.0',self.env.username,self.env.group,iologger.current_function(),'InternalError',str(type) + ':' + str(value))
            raise ValueError('Unable to bind to socket')
        
    def main_loop(self,timeout):
        asyncore.loop(timeout=timeout,use_poll=True,map=self.map)
            
    def handle_accept(self):
        try:
            conn,addr = self.accept()
            self.log.log_error(iologger.DEBUG,str(addr[0]),self.env.username,self.env.group,iologger.current_function(),'OK','')
            c = asyncconnection.IOAsyncConnection(conn,addr[0],self.map,self.userclass,self.iotrees,self.log)
            asyncore.dispatcher.add_channel(c, self.map)
        except:
            type,value = sys.exc_info()[:2]
            self.log.log_error(iologger.ERROR,'0.0.0.0',self.env.username,self.env.group,iologger.current_function(),'InternalError',str(type) + ':' + str(value))
                        
    def handle_close(self):
        self.log.log_access('0.0.0.0',self.env.username,self.env.group,iologger.current_function(),'OK','')
                    
    def handle_connect(self):
        self.log.log_error(iologger.DEBUG,'0.0.0.0','','',iologger.current_function(),'OK','')

    def handle_error(self):
        type,value = sys.exc_info()[:2]
        self.log.log_error(iologger.CRITICAL,'0.0.0.0',self.env.username,self.env.group,iologger.current_function(),'InternalError',str(type) + ':' + str(value))
